package tech.runchen.gz5055.oms.common.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import tech.runchen.gz5055.oms.common.annotation.RequiresPermissions;
import tech.runchen.gz5055.oms.common.enums.UserType;
import tech.runchen.gz5055.oms.common.exception.RRException;
import tech.runchen.gz5055.oms.common.utils.StringUtils;
import tech.runchen.gz5055.oms.security.model.LoginUser;
import tech.runchen.gz5055.oms.security.service.TokenService;

import javax.servlet.http.HttpServletRequest;

/**
 * @author zzj
 */
@Aspect
@Component
public class RequiresPermissionsAspect {

    @Autowired
    private TokenService tokenService;

    @Before(value = "@annotation(controllerLog)")
    public void doBefore(JoinPoint joinPoint, RequiresPermissions controllerLog) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser)) {
            tokenService.verifyToken(loginUser);
        } else {
            throw new RRException("登录凭证已过期", 401);
        }
        if (!loginUser.getUser().getType().equals(UserType.ADMIN.getCode()) && !hasPerm(loginUser.getUser().getType(), controllerLog)) {
            throw new RRException("您没有权限访问该接口", 403);
        }
    }

    /**
     * 验证权限
     *
     * @param userType
     * @param controllerLog
     * @return
     */
    private boolean hasPerm(int userType, RequiresPermissions controllerLog) {
        boolean flag = false;
        for (UserType type : controllerLog.value()) {
            if (userType == type.getCode()) {
                flag = true;
                break;
            }
        }
        return flag;
    }
}
